package com.brillilab.service.logic.home;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.brillilab.common.constant.ClientTypeEnum;
import com.brillilab.common.entity.PageVo;
import com.brillilab.common.utils.DateUtil;
import com.brillilab.common.utils.MyBeanUtils;
import com.brillilab.domain.enums.common.BoolEnum;
import com.brillilab.domain.enums.experiment.ExperimentStateEnum;
import com.brillilab.domain.enums.kit.KitEnum;
import com.brillilab.domain.enums.lab.LabMemberEnum;
import com.brillilab.domain.enums.lab.LabMemberPowerEnum;
import com.brillilab.domain.enums.team.TeamMemberStateEnum;
import com.brillilab.domain.po.comments.ChatMessage;
import com.brillilab.domain.po.experiments.Experiment;
import com.brillilab.domain.po.experiments.ExperimentBill;
import com.brillilab.domain.po.lab.LabMember;
import com.brillilab.domain.po.lab.LabMemberPower;
import com.brillilab.domain.po.plans.Plan;
import com.brillilab.domain.po.team.Team;
import com.brillilab.domain.po.team.TeamMember;
import com.brillilab.domain.po.topics.TopicTarget;
import com.brillilab.domain.vo.comments.CommentsGuideVo;
import com.brillilab.domain.vo.experiments.ExperimentDateRangeStatVo;
import com.brillilab.domain.vo.experiments.ExperimentMemberCompleteStatVo;
import com.brillilab.domain.vo.home.*;
import com.brillilab.domain.vo.kit.KitUsageChartVo;
import com.brillilab.domain.vo.lab.MemberInfoVo;
import com.brillilab.domain.vo.notice.NoticeSearch;
import com.brillilab.domain.vo.notice.NoticeVo;
import com.brillilab.domain.vo.team.TeamMemberVo;
import com.brillilab.domain.vo.topics.TopicExperimentVo;
import com.brillilab.domain.vo.topics.TopicScheduleVo;
import com.brillilab.domain.vo.user.UserInfoVo;
import com.brillilab.service.core.comments.IChatMessageService;
import com.brillilab.service.core.experiments.IExperimentBillService;
import com.brillilab.service.core.experiments.IExperimentCommentService;
import com.brillilab.service.core.experiments.IExperimentService;
import com.brillilab.service.core.kit.IKitService;
import com.brillilab.service.core.kit.IKitUsageService;
import com.brillilab.service.core.lab.ILabMemberService;
import com.brillilab.service.core.method.IMethodLabViewService;
import com.brillilab.service.core.method.IMethodService;
import com.brillilab.service.core.notice.INoticeService;
import com.brillilab.service.core.plans.IPlanService;
import com.brillilab.service.core.team.ITeamMemberService;
import com.brillilab.service.core.team.ITeamService;
import com.brillilab.service.core.topics.ITopicExperimentService;
import com.brillilab.service.core.topics.ITopicService;
import com.brillilab.service.core.topics.ITopicTargetService;
import com.brillilab.service.core.user.IInviteCodeService;
import com.brillilab.service.logic.experiments.ExperimentLogic;
import com.brillilab.service.logic.kit.KitUsageLogic;
import com.brillilab.service.logic.plans.PlanLogic;
import com.brillilab.service.logic.team.TeamLogic;
import com.brillilab.service.logic.topics.TopicLogic;
import com.brillilab.service.logic.user.UsersLogic;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class HomeLogic {

    @Resource
    private UsersLogic usersLogic;
    @Resource
    private ITeamService teamService;
    @Resource
    private ITopicService topicService;
    @Resource
    private IExperimentService experimentService;
    @Resource
    private ITopicExperimentService topicExperimentService;
    @Resource
    private IMethodService methodService;
    @Resource
    private IMethodLabViewService methodLabViewService;
    @Resource
    private INoticeService noticeService;
    @Resource
    private IKitUsageService kitUsageService;
    @Resource
    private TeamLogic teamLogic;
    @Resource
    private PlanLogic planLogic;
    @Resource
    private TopicLogic topicLogic;
    @Resource
    private ExperimentLogic experimentLogic;
    @Resource
    private KitUsageLogic kitUsageLogic;
    @Resource
    private IKitService kitService;
    @Resource
    private IExperimentCommentService experimentCommentService;
    @Resource
    private IInviteCodeService inviteCodeService;
    @Resource
    private ILabMemberService labMemberService;
    @Resource
    private HomeLogic homeLogic;
    @Resource
    private ITeamMemberService teamMemberService;
    @Resource
    private IPlanService planService;
    @Resource
    private IExperimentBillService experimentBillService;
    @Resource
    private ITopicTargetService topicTargetService;
    @Resource
    private IChatMessageService chatMessageService;

    /**
     * 首页banner列表
     *
     * @return
     */
    public List<HomeBannerVo> getBannerList(String token) {
        String client = token.split("_")[0];
        List<HomeBannerVo> bannerList = new ArrayList<>();
        if (ClientTypeEnum.PC.getValue().equals(client)) {
            bannerList.add(new HomeBannerVo(
                    "https://labinone-public.oss-cn-hangzhou.aliyuncs.com/labinone-public/index_banner1.png",
                    "https://www.labinone.com"));

        } else if (ClientTypeEnum.WEB.getValue().equals(client)) {
            bannerList.add(new HomeBannerVo(
                    "https://labinone-public.oss-cn-hangzhou.aliyuncs.com/labinone-public/index_banner1.png",
                    "https://www.labinone.com"));

        } else if (ClientTypeEnum.IOS.getValue().equals(client) || ClientTypeEnum.ANDROID.getValue().equals(client)) {
            bannerList.add(new HomeBannerVo(
                    "https://labinone-public.oss-cn-hangzhou.aliyuncs.com/labinone-public/index_app_banner1.png",
                    "https://www.labinone.com"));
        } else {
            bannerList.add(new HomeBannerVo(
                    "https://labinone-public.oss-cn-hangzhou.aliyuncs.com/labinone-public/index_banner1.png",
                    "https://www.labinone.com"));
        }
        return bannerList;
    }

    /**
     * 首页用户信息
     *
     * @return
     */
    public HomeUserInfoVo getUserInfo(UserInfoVo userVo) {
        HomeUserInfoVo info = MyBeanUtils.copyBean(userVo, HomeUserInfoVo.class);
        info.setUserId(userVo.getId());
        Team team = teamService.selectByLabMemberId(userVo.getLabMemberId());
        if (team == null) {
            Team piTeam = teamLogic.getPiTeam(userVo.getLabId());
            if (piTeam != null) {
                info.setTeamName(piTeam.getName());
            } else {
                info.setTeamName("暂无研究小组");
            }
        } else {
            info.setTeamName(team.getName());
        }
        int isReview = BoolEnum.FALSE.getValue();
        if (userVo.getIsOwner() || (team != null && userVo.getLabMemberId().equals(team.getLeaderId()))) {
            isReview = BoolEnum.TRUE.getValue();
        } else {
            List<LabMemberPower> powers = userVo.getPowers();
            if (CollUtil.isNotEmpty(powers)) {
                List<String> collect = powers.stream().map(LabMemberPower::getPower).collect(Collectors.toList());
                if (collect.contains(LabMemberPowerEnum.Power.METHOD.getValue())) {
                    isReview = BoolEnum.TRUE.getValue();
                }
            }
        }
        info.setIsReview(isReview);
        info.setLabList(usersLogic.getLabList(userVo.getId()));
        if (userVo.getIsOwner()) {
            info.setTopicNum(topicService.getTopicCountByLabId(userVo.getLabId()));
            info.setExperimentNum(topicExperimentService.getCountByLabId(userVo.getLabId()));// (experimentService.getExperimentCount(userVo.getLabId()));
            // info.setMethodNum(methodLabViewService.getMethodCount(userVo.getLabId()));
            info.setMethodNum(0);// 默认值
            List<LabMember> labMembers = labMemberService.selectPoList(userVo.getLabId(),
                    LabMemberEnum.State.STATE_IN.getValue());
            if (CollUtil.isNotEmpty(labMembers)) {
                List<Long> usersIdList = labMembers.stream().map(LabMember::getUserId).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(usersIdList)) {
                    info.setMethodNum(methodService.getMethodCountByUserIdList(usersIdList));
                }
            }
        } else {
            info.setTopicNum(topicService.getTopicCountByLabMemberId(userVo.getLabMemberId()));
            info.setExperimentNum(
                    topicExperimentService.getCountByLabMemberId(userVo.getLabId(), userVo.getLabMemberId()));// (experimentService.getExperimentCountByExecutorId(userVo.getLabMemberId()));
            info.setMethodNum(methodService.getMethodCountByUserId(userVo.getId()));
        }

        info.setRemainCount(0);
        // 邀请码信息显示
        if (userVo.getIsOwner()) {
            HomeInviteCodeInfo inviteCodeInfo = usersLogic.getInviteCodeInfo(userVo);
            if (inviteCodeInfo != null) {
                info.setShowInviteCode(inviteCodeInfo.getCodeList() != null);
                info.setRemainCount(inviteCodeInfo.getRemainCount());
                info.setInviteCodeList(inviteCodeInfo.getCodeList());
                info.setTips(inviteCodeInfo.getTips());
            }
        }
        info.setLabPayType(1);
        return info;
    }

    /**
     * 首页公告列表
     *
     * @return
     */
    public PageVo<NoticeVo> getNoticeList(UserInfoVo userVo) {
        NoticeSearch noticeSearch = new NoticeSearch();
        noticeSearch.setLabId(userVo.getLabId());
        noticeSearch.setPageNum(1);
        noticeSearch.setPageSize(5);
        PageVo<NoticeVo> page = noticeService.getAndSearchNoticeList(noticeSearch);
        return page;
    }

    /**
     * 首页成员计划完成情况统计
     *
     * @param userVo
     * @return
     */
    public HomeMemberExperimentCompleteStatVo getExperimentMemberCompleteStat(UserInfoVo userVo, Date beginDate, Date endDate) {

        HomeMemberExperimentCompleteStatVo vo = new HomeMemberExperimentCompleteStatVo();
        // 统计周期
        vo.setDateRange(DateUtil.dateString(beginDate, "M/dd") + "~" + DateUtil.dateString(endDate, "M/dd"));
        Long piMemberId;
        if (userVo.getIsOwner()) {
            piMemberId = userVo.getLabMemberId();
        } else {
            piMemberId = labMemberService.getOwner(userVo.getLabId()).getId();
        }

        // 获取当前实验室所有成员
        List<MemberInfoVo> memberList = labMemberService.selectMemberVoList(userVo.getLabId(),
                LabMemberEnum.State.STATE_IN.getValue());
        memberList = memberList.stream().filter(m -> !m.getLabMemberId().equals(piMemberId))
                .collect(Collectors.toList());

        List<ExperimentMemberCompleteStatVo> statVos = new ArrayList<>();
        if (CollUtil.isNotEmpty(memberList)) {
            // 指定成员Id集合的计划列表
            List<Long> labMemberIds = memberList.stream().map(MemberInfoVo::getLabMemberId)
                    .collect(Collectors.toList());
            List<Plan> planList = planService.getPlanListByLabMemberIdList(labMemberIds,
                    DateUtil.dateString(beginDate, "yyyy-MM-dd"),
                    DateUtil.dateString(DateUtil.addDate(endDate, 1), "yyyy-MM-dd"));
            Map<Long, List<Experiment>> experimentMap = CollUtil.newHashMap();
            if (CollUtil.isNotEmpty(planList)) {
                List<Long> experimentIds = planList.stream().map(Plan::getExperimentId).collect(Collectors.toList());
                List<Experiment> experimentList = experimentService.selectByIds(experimentIds);
                experimentMap = experimentList.stream().collect(Collectors.groupingBy(Experiment::getExecutorId));
            }

            for (MemberInfoVo member : memberList) {
                ExperimentMemberCompleteStatVo statVo = new ExperimentMemberCompleteStatVo();
                statVo.setLabMemberId(member.getLabMemberId());
                statVo.setMemberName(member.getUserName());
                statVo.setIsCanSee(userVo.getIsOwner() ? BoolEnum.TRUE.getValue() : BoolEnum.FALSE.getValue());
                List<Experiment> experList = experimentMap.get(member.getLabMemberId());
                if (CollUtil.isNotEmpty(experList)) {
                    // 待完成数量
                    List<Experiment> unCompleteList = experList.stream()
                            .filter(p -> p.getState().equals(ExperimentStateEnum.NOT_STARTED.getValue())
                                    || p.getState().equals(ExperimentStateEnum.UNDER_WAY.getValue()))
                            .collect(Collectors.toList());
                    statVo.setUnCompleteCount(unCompleteList.size());
                    // 符合预期数量
                    List<Experiment> accordList = experList.stream()
                            .filter(p -> p.getState().equals(ExperimentStateEnum.COMPLETE.getValue())
                                    && BoolEnum.TRUE.getValue().equals(p.getIsExpect()))
                            .collect(Collectors.toList());
                    statVo.setAccordCount(accordList.size());
                    // 不符合预期数量
                    List<Experiment> notAccordList = experList.stream()
                            .filter(p -> p.getState().equals(ExperimentStateEnum.COMPLETE.getValue())
                                    && BoolEnum.FALSE.getValue().equals(p.getIsExpect()))
                            .collect(Collectors.toList());
                    statVo.setNotAccordCount(notAccordList.size());
                    // 总数为上述三个值累加
                    statVo.setTotalCount(unCompleteList.size() + accordList.size() + notAccordList.size());
                }
                statVos.add(statVo);
            }
        }
        if (userVo.getIsOwner()) {
            statVos.sort(Comparator.comparing(ExperimentMemberCompleteStatVo::getMemberName));
            vo.setMemberList(statVos);
            return vo;
        } else {
            TeamMember teamMember = teamMemberService.selectByLabMemberId(userVo.getLabMemberId());
            List<Long> teamMemberIds = null;
            boolean isLeader = false;
            if (teamMember != null) {
                List<TeamMember> teamMembers = teamMemberService.selectListByTeamIdAndState(teamMember.getTeamId(),
                        TeamMemberStateEnum.IN.getState());
                teamMemberIds = teamMembers.stream().map(TeamMember::getLabMemberId).collect(Collectors.toList());
                Team team = teamService.selectById(teamMember.getTeamId());
                if (team != null)
                    isLeader = userVo.getLabMemberId().equals(team.getLeaderId());
            }

            ExperimentMemberCompleteStatVo meStatVo = null;
            List<ExperimentMemberCompleteStatVo> teamStatVoList = CollUtil.toList();
            List<ExperimentMemberCompleteStatVo> otherStatVoList = CollUtil.toList();
            for (ExperimentMemberCompleteStatVo statVo : statVos) {
                if (userVo.getLabMemberId().equals(statVo.getLabMemberId())) {
                    meStatVo = statVo;
                    meStatVo.setIsCanSee(BoolEnum.TRUE.getValue());
                } else if (CollUtil.contains(teamMemberIds, statVo.getLabMemberId())) {
                    statVo.setIsCanSee(isLeader ? BoolEnum.TRUE.getValue() : BoolEnum.FALSE.getValue());
                    teamStatVoList.add(statVo);
                } else {
                    otherStatVoList.add(statVo);
                }
            }
            if (CollUtil.isNotEmpty(teamStatVoList)) {
                CollUtil.sort(teamStatVoList, new Comparator<ExperimentMemberCompleteStatVo>() {
                    public int compare(ExperimentMemberCompleteStatVo c1, ExperimentMemberCompleteStatVo c2) {
                        return c2.getMemberName().compareTo(c1.getMemberName());
                    }
                });
            }
            if (CollUtil.isNotEmpty(otherStatVoList)) {
                CollUtil.sort(otherStatVoList, new Comparator<ExperimentMemberCompleteStatVo>() {
                    public int compare(ExperimentMemberCompleteStatVo c1, ExperimentMemberCompleteStatVo c2) {
                        return c2.getMemberName().compareTo(c1.getMemberName());
                    }
                });
            }
            List<ExperimentMemberCompleteStatVo> statVoList = CollUtil.toList();
            statVoList.add(meStatVo);
            statVoList.addAll(teamStatVoList);
            statVoList.addAll(otherStatVoList);
            vo.setMemberList(statVoList);
            return vo;
        }
    }

    /**
     * 我的物料
     *
     * @return
     */
    public HomeMaterielVo getMyMateriel(UserInfoVo userVo) {
        return kitUsageService.getMaterielVo(userVo.getLabMemberId());
    }

    /**
     * 我的本周计划
     *
     * @param labMemberId
     * @return
     */
    public HomeWeekPlanVo getMyThisWeekPlan(Long labMemberId) {
        HomeWeekPlanVo homeWeekPlanVo = new HomeWeekPlanVo();
        Date beginDate = DateUtil.getBeginDayOfWeek();
        Date endDate = DateUtil.getEndDayOfWeek();
        // 统计周期
        homeWeekPlanVo.setStatDate(DateUtil.dateString(beginDate, "M/dd") + "~" + DateUtil.dateString(endDate, "M/dd"));
        List<Plan> planList = planService.getPlanList(labMemberId, DateUtil.addDate(beginDate, -1),
                DateUtil.addDate(endDate, 2));

        if (planList != null && planList.size() > 0) {
            // 昨日计划
            List<Plan> yesterdayPlanList = planList.stream()
                    .filter(p -> p.getPlanTime().getTime() >= DateUtil.addDate(DateUtil.getDayBegin(), -1).getTime()
                            && p.getPlanTime().getTime() < DateUtil.getDayBegin().getTime())
                    .collect(Collectors.toList());
            // 今日计划
            List<Plan> todayPlanList = planList.stream()
                    .filter(p -> p.getPlanTime().getTime() >= DateUtil.getDayBegin().getTime()
                            && p.getPlanTime().getTime() <= DateUtil.getDayEnd().getTime())
                    .collect(Collectors.toList());
            // 明日计划
            List<Plan> tomorrowPlanList = planList.stream()
                    .filter(p -> p.getPlanTime().getTime() >= DateUtil.addDate(DateUtil.getDayBegin(), 1).getTime()
                            && p.getPlanTime().getTime() < DateUtil.addDate(DateUtil.getDayBegin(), 2).getTime())
                    .collect(Collectors.toList());
            // 本周计划
            List<Plan> thisPlanList = planList.stream()
                    .filter(p -> p.getPlanTime().getTime() >= beginDate.getTime()
                            && p.getPlanTime().getTime() < DateUtil.addDate(endDate, 1).getTime())
                    .collect(Collectors.toList());

            // 获取计划列表中的实验Id集合
            List<Long> experimentIdList = planList.stream().map(Plan::getExperimentId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(experimentIdList)) {
                // 获取实验列表（本周计划的所有实验）
                List<Experiment> experimentList = experimentService.selectByIds(experimentIdList);
                if (experimentList != null && experimentList.size() > 0) {
                    // 本周实验列表
                    List<Long> thisWeekIdList = thisPlanList.stream().map(Plan::getExperimentId)
                            .collect(Collectors.toList());
                    if (CollUtil.isEmpty(thisWeekIdList)) {
                        // 周计划为空时，返回初始化数据
                        homeWeekPlanVo = getInitPlanCompleteStatInfo(homeWeekPlanVo.getStatDate());
                    } else {

                        // 周计划实验统计
                        HomePlanCompleteVo weekStat = getPlanCompleteStatInfo(thisWeekIdList, experimentList);
                        homeWeekPlanVo.setThisWeek(weekStat);

                        // 昨日实验列表
                        List<Long> yesterdayIdList = yesterdayPlanList.stream().map(Plan::getExperimentId)
                                .collect(Collectors.toList());
                        HomePlanCompleteVo yesterdayStat = getPlanCompleteStatInfo(yesterdayIdList, experimentList);
                        homeWeekPlanVo.setYesterday(yesterdayStat);

                        // 今日实验列表
                        List<Long> todayIdList = todayPlanList.stream().map(Plan::getExperimentId)
                                .collect(Collectors.toList());
                        HomePlanCompleteVo todayStat = getPlanCompleteStatInfo(todayIdList, experimentList);
                        homeWeekPlanVo.setToday(todayStat);

                        // 明日实验列表
                        List<Long> tomorrowIdList = tomorrowPlanList.stream().map(Plan::getExperimentId)
                                .collect(Collectors.toList());
                        HomePlanCompleteVo tomorrowStat = getPlanCompleteStatInfo(tomorrowIdList, experimentList);
                        homeWeekPlanVo.setTomorrow(tomorrowStat);
                    }
                }
            } else {
                // 无实验时，返回初始化数据
                homeWeekPlanVo = getInitPlanCompleteStatInfo(homeWeekPlanVo.getStatDate());
            }
        } else {
            // 无计划时返回初始化数据
            homeWeekPlanVo = getInitPlanCompleteStatInfo(homeWeekPlanVo.getStatDate());
        }

        return homeWeekPlanVo;
    }

    /**
     * 无计划时返回数据
     *
     * @param statDate
     * @return
     */
    private HomeWeekPlanVo getInitPlanCompleteStatInfo(String statDate) {
        HomeWeekPlanVo homeWeekPlanVo = new HomeWeekPlanVo();

        homeWeekPlanVo.setStatDate(statDate);
        HomePlanCompleteVo homePlanCompleteVo = new HomePlanCompleteVo();
        homePlanCompleteVo.setUnComplete(0);
        homePlanCompleteVo.setComplete(0);
        homePlanCompleteVo.setTotalCount(0);

        homeWeekPlanVo.setYesterday(homePlanCompleteVo);
        homeWeekPlanVo.setToday(homePlanCompleteVo);
        homeWeekPlanVo.setTomorrow(homePlanCompleteVo);
        homeWeekPlanVo.setThisWeek(homePlanCompleteVo);
        return homeWeekPlanVo;
    }

    /**
     * 获取指定实验列表的实验完成统计信息
     *
     * @param experimentIdList  待统计实验Id集合
     * @param allExperimentList 所有实验集合
     * @return
     */
    private HomePlanCompleteVo getPlanCompleteStatInfo(List<Long> experimentIdList,
                                                       List<Experiment> allExperimentList) {
        HomePlanCompleteVo homePlanCompleteVo = new HomePlanCompleteVo();
        if (CollUtil.isNotEmpty(experimentIdList)) {
            // 待统计实验Id集合中，实际含有的实验列表
            List<Experiment> experimentList = allExperimentList.stream()
                    .filter(p -> experimentIdList.contains(p.getId())).collect(Collectors.toList());
            // 未完成实验列表
            List<Experiment> unCompleteList = experimentList.stream()
                    .filter(p -> p.getState().equals(ExperimentStateEnum.NOT_STARTED.getValue())
                            || p.getState().equals(ExperimentStateEnum.UNDER_WAY.getValue()))
                    .collect(Collectors.toList());
            // 已完成实验列表
            List<Experiment> completeList = experimentList.stream()
                    .filter(p -> p.getState().equals(ExperimentStateEnum.COMPLETE.getValue()))
                    .collect(Collectors.toList());

            homePlanCompleteVo.setUnComplete(unCompleteList.size() > 0 ? unCompleteList.size() : 0);
            homePlanCompleteVo.setComplete(completeList.size() > 0 ? completeList.size() : 0);
            homePlanCompleteVo.setTotalCount(experimentList.size());
        } else {
            homePlanCompleteVo.setUnComplete(0);
            homePlanCompleteVo.setComplete(0);
            homePlanCompleteVo.setTotalCount(0);
        }
        return homePlanCompleteVo;
    }

    /**
     * @return
     */
    public List<TopicExperimentVo> getTodayExperimentList(UserInfoVo userInfo) {

        List<TopicExperimentVo> topicExperimentVos = new ArrayList<>();
        List<Plan> planList = planService.getTodayPlanNoCompleteList(userInfo.getLabMemberId());
        if (CollUtil.isNotEmpty(planList)) {
            for (Plan plan : planList) {
                TopicExperimentVo experimentVo = topicLogic.getExperimentInfo(userInfo, plan.getExperimentId());
                topicExperimentVos.add(experimentVo);
            }
//			List<Long> experimentIds = planList.stream().map(Plan::getExperimentId).collect(Collectors.toList());
//			topicExperimentVos = topicLogic.getExperimentGuideList(labMemberId, experimentIds);
        }
        return topicExperimentVos;
    }

    /**
     * 首页近期实验统计
     *
     * @param labMemberId
     * @return
     */
    public List<ExperimentDateRangeStatVo> getExperimentDateRangeStat(Long labMemberId) {

        List<ExperimentDateRangeStatVo> experimentDateRangeStatVoList = new ArrayList<>();
        Date beginDate = DateUtil.addDate(DateUtil.getBeginDayOfWeek(), -21);
        Date endDate = DateUtil.getEndDayOfWeek();

        List<Plan> planList = planService.getPlanList(labMemberId, beginDate, endDate);

        if (!CollectionUtils.isEmpty(planList)) {
            // 获取计划列表中的实验Id集合
            List<Long> experimentIdList = planList.stream().map(Plan::getExperimentId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(experimentIdList)) {
                List<Experiment> experimentList = experimentService.selectByIds(experimentIdList);

                // 第一周
                ExperimentDateRangeStatVo fstWeekStatInfo = getExperimentCompleteStatInfo(planList, beginDate,
                        DateUtil.addDate(beginDate, 7), experimentList);
                experimentDateRangeStatVoList.add(fstWeekStatInfo);

                // 第二周
                ExperimentDateRangeStatVo secWeekStatInfo = getExperimentCompleteStatInfo(planList,
                        DateUtil.addDate(beginDate, 7), DateUtil.addDate(beginDate, 14), experimentList);
                experimentDateRangeStatVoList.add(secWeekStatInfo);

                // 第三周
                ExperimentDateRangeStatVo thdWeekStatInfo = getExperimentCompleteStatInfo(planList,
                        DateUtil.addDate(beginDate, 14), DateUtil.addDate(beginDate, 21), experimentList);
                experimentDateRangeStatVoList.add(thdWeekStatInfo);

                // 第四周
                ExperimentDateRangeStatVo fourthWeekStatInfo = getExperimentCompleteStatInfo(planList,
                        DateUtil.addDate(beginDate, 21), DateUtil.addDate(beginDate, 28), experimentList);
                experimentDateRangeStatVoList.add(fourthWeekStatInfo);
            } else {
                // 有计划无实验时，初始化统计指标
                experimentDateRangeStatVoList = getInitExperimentCompleteStatInfo(beginDate);
            }
        } else {
            // 无实验计划时，初始化统计指标
            experimentDateRangeStatVoList = getInitExperimentCompleteStatInfo(beginDate);
        }
        return experimentDateRangeStatVoList;
    }

    /**
     * 初始化实验完成情况统计
     *
     * @param beginDate
     * @return
     */
    private List<ExperimentDateRangeStatVo> getInitExperimentCompleteStatInfo(Date beginDate) {
        List<ExperimentDateRangeStatVo> experimentDateRangeStatVoList = new LinkedList<>();
        ExperimentDateRangeStatVo experimentDateRangeStatVo;

        for (int i = 0; i < 4; i++) {
            Date startTime = DateUtil.addDate(beginDate, i * 7);
            Date endTime = DateUtil.addDate(beginDate, (i + 1) * 7 - 1);
            experimentDateRangeStatVo = new ExperimentDateRangeStatVo();
            experimentDateRangeStatVo
                    .setDateRange(DateUtil.dateString(startTime, "M/dd") + "~" + DateUtil.dateString(endTime, "M/dd"));
            experimentDateRangeStatVo.setUnCompleteCount(0);
            experimentDateRangeStatVo.setAccordCount(0);
            experimentDateRangeStatVo.setNotAccordCount(0);
            experimentDateRangeStatVo.setTotalCount(0);
            experimentDateRangeStatVoList.add(experimentDateRangeStatVo);
        }
        return experimentDateRangeStatVoList;
    }

    /**
     * 实验区间统计
     *
     * @param planList          计划集合
     * @param beginDate         起始日期
     * @param endDate           截止日期
     * @param allExperimentList 时间区间内的所有实验集合
     * @return
     */
    private ExperimentDateRangeStatVo getExperimentCompleteStatInfo(List<Plan> planList, Date beginDate, Date endDate,
                                                                    List<Experiment> allExperimentList) {
        ExperimentDateRangeStatVo experimentDateRangeStatVo = new ExperimentDateRangeStatVo();
        experimentDateRangeStatVo.setDateRange(DateUtil.dateString(beginDate, "M/dd") + "~"
                + DateUtil.dateString(DateUtil.addDate(endDate, -1), "M/dd"));
        List<Plan> statPlanList = planList.stream().filter(
                p -> p.getPlanTime().getTime() >= beginDate.getTime() && p.getPlanTime().getTime() < endDate.getTime())
                .collect(Collectors.toList());

        // 待统计实验ID集合
        List<Long> experimentIdList = statPlanList.stream().map(Plan::getExperimentId).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(experimentIdList)) {
            // 待统计实验Id集合中，实际含有的实验列表
            List<Experiment> experimentList = allExperimentList.stream()
                    .filter(p -> experimentIdList.contains(p.getId())).collect(Collectors.toList());
            // 待完成数量
            List<Experiment> unCompleteList = experimentList.stream()
                    .filter(p -> p.getState().equals(ExperimentStateEnum.NOT_STARTED.getValue())
                            || p.getState().equals(ExperimentStateEnum.UNDER_WAY.getValue()))
                    .collect(Collectors.toList());
            // 符合预期数量
            List<Experiment> accordList = experimentList.stream()
                    .filter(p -> p.getState().equals(ExperimentStateEnum.COMPLETE.getValue())
                            && BoolEnum.TRUE.getValue().equals(p.getIsExpect()))
                    .collect(Collectors.toList());
            // 不符合预期数量
            List<Experiment> notAccordList = experimentList.stream()
                    .filter(p -> p.getState().equals(ExperimentStateEnum.COMPLETE.getValue())
                            && BoolEnum.FALSE.getValue().equals(p.getIsExpect()))
                    .collect(Collectors.toList());

            experimentDateRangeStatVo.setUnCompleteCount(unCompleteList.size() > 0 ? unCompleteList.size() : 0);
            experimentDateRangeStatVo.setAccordCount(accordList.size() > 0 ? accordList.size() : 0);
            experimentDateRangeStatVo.setNotAccordCount(notAccordList.size() > 0 ? notAccordList.size() : 0);
            experimentDateRangeStatVo.setTotalCount(unCompleteList.size() + accordList.size() + notAccordList.size());
        } else {
            // 无实验数据时，默认值设为0
            experimentDateRangeStatVo.setUnCompleteCount(0);
            experimentDateRangeStatVo.setAccordCount(0);
            experimentDateRangeStatVo.setNotAccordCount(0);
            experimentDateRangeStatVo.setTotalCount(0);
        }
        return experimentDateRangeStatVo;
    }

    /**
     * 近期试剂关联试剂情况统计
     *
     * @param labId
     * @param labMemberId
     * @return
     */
    public List<KitUsageChartVo> getMyKitStat(Long labId, Long labMemberId) {
        List<KitUsageChartVo> kitUsageChartVoList = new ArrayList<>();
        Date beginDate = DateUtil.addDate(DateUtil.getBeginDayOfWeek(), -21);
        Date endDate = DateUtil.getEndDayOfWeek();

        List<Experiment> experimentList = experimentService.getExperimentList(labMemberId, beginDate, endDate);
        List<ExperimentBill> billList = null;
        if (!CollectionUtils.isEmpty(experimentList)) {
            List<Long> experimentIdList = experimentList.stream().map(Experiment::getId).collect(Collectors.toList());
            billList = experimentBillService.getBillChartByDateRange(experimentIdList, beginDate, endDate);
        }
        if (!CollectionUtils.isEmpty(billList)) {
            // 第一周
            KitUsageChartVo fstWeekStatInfo = getExperimentBillStatInfo(billList, beginDate,
                    DateUtil.addDate(beginDate, 7));
            kitUsageChartVoList.add(fstWeekStatInfo);

            // 第二周
            KitUsageChartVo secWeekStatInfo = getExperimentBillStatInfo(billList, DateUtil.addDate(beginDate, 7),
                    DateUtil.addDate(beginDate, 14));
            kitUsageChartVoList.add(secWeekStatInfo);

            // 第三周
            KitUsageChartVo thdWeekStatInfo = getExperimentBillStatInfo(billList, DateUtil.addDate(beginDate, 14),
                    DateUtil.addDate(beginDate, 21));
            kitUsageChartVoList.add(thdWeekStatInfo);

            // 第四周
            KitUsageChartVo fourthWeekStatInfo = getExperimentBillStatInfo(billList, DateUtil.addDate(beginDate, 21),
                    DateUtil.addDate(beginDate, 28));
            kitUsageChartVoList.add(fourthWeekStatInfo);
        } else {
            // 无数据时，初始化数据记录
            kitUsageChartVoList = getInitUsageStatInfo(beginDate);
        }

        return kitUsageChartVoList;
    }

    /**
     * 指定区间内的样品清单统计
     *
     * @param beginDate
     * @param endDate
     * @return
     */
    private KitUsageChartVo getExperimentBillStatInfo(List<ExperimentBill> billList, Date beginDate, Date endDate) {
        KitUsageChartVo kitUsageChartVo = new KitUsageChartVo();
        kitUsageChartVo.setDateRange(DateUtil.dateString(beginDate, "M/dd") + "~"
                + DateUtil.dateString(DateUtil.addDate(endDate, -1), "M/dd"));
        // 获取指定区间的取用数量
        List<ExperimentBill> statList = billList.stream().filter(p -> p.getCreateTime().getTime() >= beginDate.getTime()
                && p.getCreateTime().getTime() < endDate.getTime()).collect(Collectors.toList());
        kitUsageChartVo.setTakeCount(statList.size());
        return kitUsageChartVo;
    }

    /**
     * 初始化无数据集合
     *
     * @param beginDate
     * @return
     */
    public List<KitUsageChartVo> getInitUsageStatInfo(Date beginDate) {
        List<KitUsageChartVo> kitUsageChartVoList = new LinkedList<>();
        KitUsageChartVo kitUsageChartVo;
        for (int i = 0; i < 4; i++) {
            Date startTime = DateUtil.addDate(beginDate, i * 7);
            Date endTime = DateUtil.addDate(beginDate, (i + 1) * 7 - 1);
            kitUsageChartVo = new KitUsageChartVo();
            kitUsageChartVo
                    .setDateRange(DateUtil.dateString(startTime, "M/dd") + "~" + DateUtil.dateString(endTime, "M/dd"));
            kitUsageChartVo.setTakeCount(0);
            kitUsageChartVoList.add(kitUsageChartVo);
        }
        return kitUsageChartVoList;
    }

    /**
     * @Description: 获取实验台数据
     * @Param:
     */
    public Map<String, Integer> getExperimentPlatData(UserInfoVo userInfoVo) {
        Map<String, Integer> result = new HashMap<>();
        if (userInfoVo.getDuty().equals("PI")) {
            result.put("topic", topicService.getTopicCount(userInfoVo.getLabId()));
        } else {
            result.put("topic", topicService.getTopicCountByLabMemberId(userInfoVo.getLabMemberId()));
        }
        result.put("method", methodService.getMethodCountByUserId(userInfoVo.getId()));
        result.put("reagent", kitService.getKitCount(userInfoVo.getLabId(), KitEnum.Classify.REAGENT));
        result.put("sample", kitService.getKitCount(userInfoVo.getLabId(), KitEnum.Classify.SAMPLE));
        return result;
    }


    /**
     * 首页实验指导-评论列表
     *
     * @return
     */
    public List<CommentsGuideVo> getCommentsGuideList(UserInfoVo userInfoVo) {
        List<CommentsGuideVo> commentGuideList = CollUtil.toList();
        List<Long> fromMemberIds = CollUtil.toList();
        Long labId = userInfoVo.getLabId();
        long labMemeberId = userInfoVo.getLabMemberId();
        Long piMemberId = labMemberService.getOwner(labId).getId();
        fromMemberIds.add(piMemberId);
        TeamMemberVo leader = teamLogic.getLeaderOfTeamMember(labId, labMemeberId);
        if (leader != null && labMemeberId != leader.getLabMemberId()) {
            fromMemberIds.add(leader.getLabMemberId());
        }
        fromMemberIds = CollUtil.distinct(fromMemberIds);
        List<ChatMessage> chatList = chatMessageService.getCommentsGuideList(fromMemberIds, labMemeberId);
        if (CollUtil.isNotEmpty(chatList)) {
            List<MemberInfoVo> memberList = labMemberService.selectMemberVoListByIds(fromMemberIds);
            for (ChatMessage chat : chatList) {
                MemberInfoVo infoVo = memberList.stream().filter(e -> e.getLabMemberId().equals(chat.getFromMemberId())).findFirst().orElse(null);
                if (infoVo != null) {
                    String content = String.format(
                            "<span style='color:#F6AC2D'>%s</span><span>在你的</span><span style='color:#F6AC2D'>%s</span><span>实验下添加了评论</span>",
                            infoVo.getUserName(), chat.getTitle());

                    CommentsGuideVo guideVo = new CommentsGuideVo();
                    guideVo.setContent(content);
                    guideVo.setCommentId(chat.getCommentId());
                    guideVo.setExperimentId(chat.getClassifyId());
                    guideVo.setLabMemberId(chat.getFromMemberId());
                    guideVo.setUserName(infoVo.getUserName());
                    guideVo.setImageUrl(infoVo.getImageUrl());
                    guideVo.setMobile(infoVo.getMobile());
                    commentGuideList.add(guideVo);
                }
            }
        }
        return commentGuideList;
    }


    /**
     * 首页实验指导成员列表
     *
     * @param userVo
     * @return
     */
    //下一版发布删除
    @Deprecated
    public List<HomeExperimentGuideMembersVo> getExperimentGuidMemberList(UserInfoVo userVo) {
        List<HomeExperimentGuideMembersVo> homeExperimentGuideMembersVoList = new ArrayList<>();

        List<MemberInfoVo> memberList = topicLogic.getOptionalExecutorList(userVo.getLabId(), userVo.getLabMemberId(),
                userVo.getIsOwner());
        memberList = memberList.stream().filter(p -> !p.getLabMemberId().equals(userVo.getLabMemberId()))
                .collect(Collectors.toList());
        List<Long> labMemberIdList = memberList.stream().map(MemberInfoVo::getLabMemberId).collect(Collectors.toList());
        Map<Long, List<Experiment>> experimentMap = null;
        if (!CollectionUtils.isEmpty(labMemberIdList)) {
            // 获取所有成员关联课题的实验列表
            List<Experiment> experimentList = experimentService.getGuideExperimentList(userVo.getLabId(),
                    userVo.getIsOwner() ? null : labMemberIdList);
            experimentMap = experimentList.stream().collect(Collectors.groupingBy(Experiment::getExecutorId));
        }
        HomeExperimentGuideMembersVo homeExperimentGuideMembersVo;
        for (MemberInfoVo member : memberList) {
            homeExperimentGuideMembersVo = new HomeExperimentGuideMembersVo();
            homeExperimentGuideMembersVo.setLabMemberId(member.getLabMemberId());
            homeExperimentGuideMembersVo.setUserName(member.getUserName());
            homeExperimentGuideMembersVo.setImageUrl(member.getImageUrl());
            homeExperimentGuideMembersVo.setMobile(member.getMobile());
            if (experimentMap != null && experimentMap.size() > 0) {
                if (CollectionUtils.isNotEmpty(experimentMap.get(member.getLabMemberId()))) {
                    homeExperimentGuideMembersVo.setIsShowRedDot(BoolEnum.TRUE.getValue());
                }
            }
            homeExperimentGuideMembersVoList.add(homeExperimentGuideMembersVo);
        }
        // 成员列表排序处理（显示红点的成员排前面）
        if (!CollectionUtils.isEmpty(homeExperimentGuideMembersVoList)) {
            homeExperimentGuideMembersVoList.sort(Comparator.comparing(HomeExperimentGuideMembersVo::getUserName));
            homeExperimentGuideMembersVoList
                    .sort(Comparator.comparing(HomeExperimentGuideMembersVo::getIsShowRedDot).reversed());
        }

        return homeExperimentGuideMembersVoList;
    }

    /**
     * 首页实验指导成员列表
     *
     * @param userVo
     * @return
     */
    public List<HomeExperimentGuideMembersVo> getGuideMemberList(UserInfoVo userVo) {
        List<HomeExperimentGuideMembersVo> voList = new ArrayList<>();

        List<MemberInfoVo> memberList = topicLogic.getOptionalExecutorList(userVo.getLabId(), userVo.getLabMemberId(),
                userVo.getIsOwner());
        memberList = memberList.stream().filter(p -> !p.getLabMemberId().equals(userVo.getLabMemberId()))
                .collect(Collectors.toList());
        List<Long> labMemberIds = memberList.stream().map(MemberInfoVo::getLabMemberId).collect(Collectors.toList());
        Map<Long, List<ChatMessage>> chatMap = null;
        if (!CollectionUtils.isEmpty(labMemberIds)) {
            List<ChatMessage> chatList = chatMessageService.getNoReadCard(labMemberIds, userVo.getLabMemberId());
            chatMap = chatList.stream().collect(Collectors.groupingBy(ChatMessage::getFromMemberId));
        }
        for (MemberInfoVo member : memberList) {
            HomeExperimentGuideMembersVo membersVo = new HomeExperimentGuideMembersVo();
            membersVo.setLabMemberId(member.getLabMemberId());
            membersVo.setUserName(member.getUserName());
            membersVo.setImageUrl(member.getImageUrl());
            membersVo.setMobile(member.getMobile());
            if (CollUtil.isNotEmpty(chatMap)) {
                if (CollectionUtils.isNotEmpty(chatMap.get(member.getLabMemberId()))) {
                    ChatMessage chat = chatMap.get(member.getLabMemberId()).get(0);
                    if (StrUtil.isNotBlank(chat.getContent())) {
                        if (chat.getContent().contains("实验分组")) {
                            membersVo.setIsHaveIcon(1);
                        } else if (chat.getContent().contains("分析后数据")) {
                            membersVo.setIsHaveIcon(2);
                        }
                    }
                }
            }
            voList.add(membersVo);
        }
        // 成员列表排序处理
        if (CollUtil.isNotEmpty(voList)) {
            CollUtil.sort(voList, new Comparator<HomeExperimentGuideMembersVo>() {
                public int compare(HomeExperimentGuideMembersVo c1, HomeExperimentGuideMembersVo c2) {
                    int i = c2.getIsHaveIcon() - c1.getIsHaveIcon();
                    if (i == 0) {
                        return c2.getUserName().compareTo(c1.getUserName());
                    }
                    return i > 0 ? 1 : -1;
                }
            });
        }
        return voList;
    }

    /**
     * 首页实验指导动态列表
     *
     * @param selectMemberId 选中成员ID
     * @param userVo         操作人用户信息
     * @return
     */
    @Deprecated
    public HomeMemberDynamicVo getMemberDynamicInfo(Long selectMemberId, UserInfoVo userVo) {
        List<MemberInfoVo> memberList = labMemberService.selectMemberVoListByIds(Arrays.asList(selectMemberId));
        Assert.isTrue(CollectionUtils.isNotEmpty(memberList), "成员不存在");
        MemberInfoVo infoVo = memberList.get(0);
        HomeMemberDynamicVo homeMemberDynamicVo = new HomeMemberDynamicVo();
        homeMemberDynamicVo.setLabMemberId(selectMemberId);
        homeMemberDynamicVo.setUserName(infoVo.getUserName());
        homeMemberDynamicVo.setImageUrl(infoVo.getImageUrl());
        homeMemberDynamicVo.setIsTop(1);

        // 获取所有成员关联课题的实验列表
        List<Experiment> experimentList = experimentService.getGuideExperimentList(userVo.getLabId(),
                Arrays.asList(selectMemberId));
        List<Long> experimentIds = experimentList.stream().map(Experiment::getId).collect(Collectors.toList());
        List<TopicExperimentVo> experimentGuideList = topicLogic.getExperimentGuideList(userVo.getLabMemberId(),
                experimentIds);
        homeMemberDynamicVo.setCardList(experimentGuideList);

        return homeMemberDynamicVo;
    }

    /**
     * 首页实验指导-实验列表
     *
     * @param labMemberId
     * @param userInfoVo
     * @return
     */
    public HomeExperimentGuideVo getExperimentGuideList(Long labMemberId, UserInfoVo userInfoVo) {
        List<MemberInfoVo> memberList = labMemberService.selectMemberVoListByIds(Arrays.asList(labMemberId));
        Assert.isTrue(CollectionUtils.isNotEmpty(memberList), "成员不存在");
        MemberInfoVo infoVo = memberList.get(0);

        HomeExperimentGuideVo guideVo = new HomeExperimentGuideVo();
        guideVo.setLabMemberId(labMemberId);
        guideVo.setUserName(infoVo.getUserName());
        guideVo.setImageUrl(infoVo.getImageUrl());
        guideVo.setIsTop(1);
        List<HomeExperimentGuideTargetVo> guideTargetList = CollUtil.newArrayList();
        guideVo.setTargetList(guideTargetList);
        // 获取所有成员关联课题的实验列表
        List<Experiment> experimentList = experimentService.getGuideExperimentList(userInfoVo.getLabId(), Arrays.asList(labMemberId));
        if (CollUtil.isEmpty(experimentList))
            return guideVo;
        List<Long> experimentIds = experimentList.stream().map(Experiment::getId).collect(Collectors.toList());
        List<TopicExperimentVo> experimentGuideList = topicLogic.getExperimentGuideList(userInfoVo.getLabMemberId(), experimentIds);
        if (CollUtil.isNotEmpty(experimentGuideList)) {
            List<Long> topicTargetIds = experimentGuideList.stream().map(TopicExperimentVo::getTopicTargetId).collect(Collectors.toList());
            Map<Long, List<TopicExperimentVo>> experimentMap = experimentGuideList.stream().collect(Collectors.groupingBy(TopicExperimentVo::getTopicTargetId));
            List<TopicTarget> targetList = topicTargetService.selectByIds(topicTargetIds);

            for (TopicTarget topicTarget : targetList) {
                HomeExperimentGuideTargetVo targetVo = new HomeExperimentGuideTargetVo();
                targetVo.setTopicId(topicTarget.getTopicId());
                targetVo.setTopicDirectionId(topicTarget.getTopicDirectionId());
                targetVo.setTopicTargetId(topicTarget.getId());
                targetVo.setTopicTargetName(topicTarget.getName());
                targetVo.setFigure(topicTarget.getFigure());
                targetVo.setColor(topicTarget.getColor());
                targetVo.setCardList(experimentMap.get(topicTarget.getId()));
                guideTargetList.add(targetVo);
            }
        }
        return guideVo;
    }

    /**
     * 获取课题进度
     *
     * @return
     */
    public PageVo<TopicScheduleVo> getTopicSchedule(UserInfoVo userInfoVo, int pageNum, int pageSize) {
        List<Long> memberIds = CollUtil.toList();
        if (userInfoVo.getIsOwner()) {
            memberIds = labMemberService.selectMemberIds(userInfoVo.getLabId(), LabMemberEnum.State.STATE_IN.getValue());
        } else {
            boolean isLeader = teamLogic.isLeaderOrPi(userInfoVo.getLabId(), userInfoVo.getLabMemberId());
            if (isLeader) {
                TeamMember teamMember = teamMemberService.selectOneByLabIdAndLabMemberId(userInfoVo.getLabId(), userInfoVo.getLabMemberId());
                List<TeamMember> teamList = teamMemberService.selectListByTeamIdAndState(teamMember.getTeamId(), TeamMemberStateEnum.IN.getState());
                memberIds = teamList.stream().map(TeamMember::getLabMemberId).collect(Collectors.toList());
            }
        }
        memberIds.add(userInfoVo.getLabMemberId());

        return topicService.getTopicSchedule(userInfoVo.getLabId(), memberIds, pageNum, pageSize);
    }


}
